package com.example.smartwaterapi.service;

import com.alibaba.fastjson2.JSON;
import com.example.smartwaterapi.common.api.RestApiResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 智能降级服务
 * 当系统限流时提供缓存数据或默认响应
 */
@Slf4j
@Service
public class DegradationService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    private static final String CACHE_PREFIX = "degradation_cache:";
    
    /**
     * 获取用户相关接口的降级数据
     */
    public RestApiResponse<Object> getUserProfileFallback(Long userId) {
        log.info("用户资料接口降级处理，用户ID: {}", userId);
        
        // 尝试从缓存获取用户基本信息
        Object cachedProfile = getCachedData("user_profile:" + userId);
        if (cachedProfile != null) {
            log.info("返回缓存的用户资料，用户ID: {}", userId);
            return RestApiResponse.ok("已为您提供缓存数据", cachedProfile);
        }
        
        // 返回默认用户信息结构
        Map<String, Object> defaultProfile = new HashMap<>();
        defaultProfile.put("id", userId);
        defaultProfile.put("nickname", "智能水杯用户");
        defaultProfile.put("dailyGoal", 2000);
        defaultProfile.put("reminderEnabled", 1);
        defaultProfile.put("avatar", "");
        defaultProfile.put("message", "系统繁忙，已为您提供默认配置");
        
        return RestApiResponse.ok("系统繁忙，已为您提供默认配置", defaultProfile);
    }
    
    /**
     * 获取饮水记录接口的降级数据
     */
    public RestApiResponse<Object> getWaterRecordFallback(Long userId) {
        log.info("饮水记录接口降级处理，用户ID: {}", userId);
        
        // 尝试从缓存获取最近的饮水记录
        Object cachedRecords = getCachedData("water_records:" + userId);
        if (cachedRecords != null) {
            log.info("返回缓存的饮水记录，用户ID: {}", userId);
            return RestApiResponse.ok("已为您提供最近的记录", cachedRecords);
        }
        
        // 返回默认饮水记录结构
        Map<String, Object> defaultRecord = new HashMap<>();
        defaultRecord.put("todayWaterIntake", 0);
        defaultRecord.put("goalProgress", 0.0);
        defaultRecord.put("lastRecordTime", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        defaultRecord.put("reminderMessage", "记得及时补充水分哦～");
        defaultRecord.put("isOfflineMode", true);
        
        return RestApiResponse.ok("系统繁忙，请稍后同步最新数据", defaultRecord);
    }
    
    /**
     * 获取统计数据接口的降级数据
     */
    public RestApiResponse<Object> getStatsFallback(Long userId) {
        log.info("统计数据接口降级处理，用户ID: {}", userId);
        
        // 尝试从缓存获取统计数据
        Object cachedStats = getCachedData("user_stats:" + userId);
        if (cachedStats != null) {
            log.info("返回缓存的统计数据，用户ID: {}", userId);
            return RestApiResponse.ok("已为您提供历史统计", cachedStats);
        }
        
        // 返回默认统计数据
        Map<String, Object> defaultStats = new HashMap<>();
        defaultStats.put("weeklyAverage", 1800);
        defaultStats.put("monthlyGoalCompletion", 0.75);
        defaultStats.put("totalDays", 0);
        defaultStats.put("bestStreak", 0);
        defaultStats.put("isEstimated", true);
        defaultStats.put("message", "数据正在同步中，请稍后查看准确统计");
        
        return RestApiResponse.ok("系统繁忙，已为您提供预估数据", defaultStats);
    }
    
    /**
     * 获取设备相关接口的降级数据
     */
    public RestApiResponse<Object> getDeviceFallback(Long userId) {
        log.info("设备接口降级处理，用户ID: {}", userId);
        
        // 返回设备离线模式提示
        Map<String, Object> deviceStatus = new HashMap<>();
        deviceStatus.put("isConnected", false);
        deviceStatus.put("connectionStatus", "offline");
        deviceStatus.put("batteryLevel", -1);  // -1 表示未知
        deviceStatus.put("lastSyncTime", "");
        deviceStatus.put("offlineModeEnabled", true);
        deviceStatus.put("message", "设备处于离线模式，部分功能受限");
        deviceStatus.put("suggestion", "请检查设备连接状态，稍后重试");
        
        return RestApiResponse.ok("设备离线模式", deviceStatus);
    }
    
    /**
     * 通用降级处理
     */
    public RestApiResponse<Object> getGenericFallback(String apiType, Long userId) {
        log.info("通用接口降级处理，接口类型: {}, 用户ID: {}", apiType, userId);
        
        Map<String, Object> fallbackData = new HashMap<>();
        fallbackData.put("isOfflineMode", true);
        fallbackData.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        fallbackData.put("message", "系统繁忙，请稍后重试");
        fallbackData.put("retryAfter", 60);
        
        switch (apiType) {
            case "upload":
                fallbackData.put("uploadStatus", "queued");
                fallbackData.put("suggestion", "文件已加入上传队列，将在网络恢复后自动上传");
                break;
            case "auth":
                fallbackData.put("authStatus", "throttled");
                fallbackData.put("suggestion", "登录请求过于频繁，请稍后重试");
                break;
            default:
                fallbackData.put("suggestion", "服务暂时不可用，请稍后重试");
        }
        
        return RestApiResponse.ok("服务降级中", fallbackData);
    }
    
    /**
     * 缓存数据用于降级
     */
    public void cacheDataForDegradation(String cacheKey, Object data, int expireMinutes) {
        try {
            String redisKey = CACHE_PREFIX + cacheKey;
            redisTemplate.opsForValue().set(redisKey, JSON.toJSONString(data), expireMinutes, TimeUnit.MINUTES);
            log.debug("缓存降级数据: {}, 过期时间: {}分钟", redisKey, expireMinutes);
        } catch (Exception e) {
            log.error("缓存降级数据失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 从缓存获取降级数据
     */
    private Object getCachedData(String cacheKey) {
        try {
            String redisKey = CACHE_PREFIX + cacheKey;
            String cachedData = (String) redisTemplate.opsForValue().get(redisKey);
            if (cachedData != null) {
                return JSON.parse(cachedData);
            }
        } catch (Exception e) {
            log.error("获取缓存降级数据失败: {}", e.getMessage(), e);
        }
        return null;
    }
    
    /**
     * 检查是否应该启用降级模式
     */
    public boolean shouldEnableDegradation(String apiType) {
        try {
            String rateLimitKey = "system_degradation:" + apiType;
            String degradationStatus = (String) redisTemplate.opsForValue().get(rateLimitKey);
            return "enabled".equals(degradationStatus);
        } catch (Exception e) {
            log.error("检查降级状态失败: {}", e.getMessage(), e);
            return false;
        }
    }
    
    /**
     * 启用系统降级模式
     */
    public void enableSystemDegradation(String apiType, int durationMinutes) {
        try {
            String rateLimitKey = "system_degradation:" + apiType;
            redisTemplate.opsForValue().set(rateLimitKey, "enabled", durationMinutes, TimeUnit.MINUTES);
            log.warn("启用系统降级模式: {}, 持续时间: {}分钟", apiType, durationMinutes);
        } catch (Exception e) {
            log.error("启用系统降级模式失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 关闭系统降级模式
     */
    public void disableSystemDegradation(String apiType) {
        try {
            String rateLimitKey = "system_degradation:" + apiType;
            redisTemplate.delete(rateLimitKey);
            log.info("关闭系统降级模式: {}", apiType);
        } catch (Exception e) {
            log.error("关闭系统降级模式失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 记录降级指标
     */
    public void recordDegradationMetrics(String apiType, Long userId, String reason) {
        try {
            String metricsKey = "degradation_metrics:" + apiType + ":" + 
                LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH"));
            
            redisTemplate.opsForHash().increment(metricsKey, "count", 1);
            redisTemplate.opsForHash().put(metricsKey, "lastUser", String.valueOf(userId));
            redisTemplate.opsForHash().put(metricsKey, "lastReason", reason);
            redisTemplate.opsForHash().put(metricsKey, "lastTime", 
                LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            
            // 设置过期时间为7天
            redisTemplate.expire(metricsKey, 7, TimeUnit.DAYS);
            
        } catch (Exception e) {
            log.error("记录降级指标失败: {}", e.getMessage(), e);
        }
    }
}
